type reponse = 
  | Accepte
  | Refuse
  | Interrompu

exception Requete_en_cours

class virtual t =
object(self)
  val joueur: Tarotv.t = Tarotv.make ()
  method virtual envoyer: Protocole.msg -> unit
  method receptionner msg =
    match msg with
    | Protocole.Deconnexion ->
       Tarotv.assimiler_information_deconnexion joueur
    | Protocole.ErreurProtocole
    | Protocole.Refuse ->
       Tarotv.assimiler_information_erreur joueur
    | Protocole.Identifier _
    | Protocole.Inviter _ -> ()
    | Protocole.Entree nom ->
       Tarotv.assimiler_information_entree joueur nom
    | Protocole.Sortie nom ->
       Tarotv.assimiler_information_sortie joueur nom
    | Protocole.Noms noms -> 
       Tarotv.assimiler_information_noms joueur noms
    | Protocole.Numero i -> 
       Tarotv.assimiler_information_numero joueur i
    | Protocole.Distribution cartes -> 
       Tarotv.assimiler_information_distribution joueur (Array.to_list cartes)
    | Protocole.Prise _ -> ()
    | Protocole.Contrat x ->
       Tarotv.assimiler_information_contrat  joueur x
    | Protocole.Appel ->
       Tarotv.assimiler_information_appel joueur
    | Protocole.Appeler _ -> ()
    | Protocole.ContratFinal (preneur, prise, appel) ->
       Tarotv.assimiler_information_contrat_final joueur preneur
						  prise appel
    | Protocole.Chien cartes ->
       Tarotv.assimiler_information_chien joueur (Array.to_list cartes)
    | Protocole.Ecart _ -> ()
    | Protocole.Atout cartes ->
       Tarotv.assimiler_information_atout_au_chien joueur cartes
    | Protocole.Jeu ->
       Tarotv.assimiler_information_jeu joueur
    | Protocole.Requete _ -> ()
    | Protocole.Carte c ->
     Tarotv.assimiler_information_carte joueur c
    | Protocole.Pli j ->
       Tarotv.assimiler_information_pli joueur j
    | Protocole.Resultat res ->
       Tarotv.assimiler_information_resultat joueur res
  method est_connecte = Tarotv.est_connecte joueur
  method mon_nom = Tarotv.mon_nom joueur
  method joueurs_disponibles = Tarotv.joueurs_disponibles joueur
  method mes_adversaires = Tarotv.mes_adversaires joueur
  method en_jeu = Tarotv.en_jeu joueur
  method mon_numero = Tarotv.mon_numero joueur
  method enchere_de = Tarotv.enchere_de joueur
  method preneur = Tarotv.preneur joueur
  method carte_appelee = Tarotv.carte_appelee joueur
  method ecart_connu = Tarotv.ecart_connu joueur
  method mon_jeu = Tarotv.mon_jeu joueur
  method chien = Tarotv.chien joueur
  method repartition_cartes = Tarotv.repartition_cartes joueur
  method joueur_maitre = Tarotv.joueur_maitre joueur
  method pli_termine = Tarotv.pli_termine joueur
  method nombre_plis_joues = Tarotv.nombre_plis_joues joueur
  method couleur_ouverture = Tarotv.couleur_ouverture joueur
  method joueur_ouverture = Tarotv.joueur_ouverture joueur 
  method requete_en_cours = Tarotv.requete_en_cours joueur
  method doit_priser = Tarotv.doit_priser joueur
  method enchere_maximale = Tarotv.enchere_maximale joueur
  method doit_appeler = Tarotv.doit_appeler joueur
  method cartes_appelables = Tarotv.cartes_appelables joueur
  method peut_appeler = Tarotv.peut_appeler joueur
  method doit_ecarter = Tarotv.doit_ecarter joueur 
  method carte_ecartable_marginale = Tarotv.carte_ecartable_marginale joueur
  method peut_ecarter = Tarotv.peut_ecarter joueur
  method doit_jouer = Tarotv.doit_jouer joueur
  method cartes_jouables = Tarotv.cartes_jouables joueur
  method peut_jouer = Tarotv.peut_jouer joueur
  method deconnecter = 
    Tarotv.assimiler_requete_deconnecter joueur;
    self#envoyer Protocole.Deconnexion
  method identifier nom reponse = 
    if self#requete_en_cours then
      raise Requete_en_cours;
    Tarotv.assimiler_requete_identifier joueur nom;
    Tarotv.traiter_reponse joueur 
			   (function 
			     | Tarotv.Accepte -> reponse Accepte
			     | Tarotv.Refuse -> reponse Refuse
			     | Tarotv.Erreur -> reponse Interrompu);
    self#envoyer (Protocole.Identifier nom)
  method inviter noms reponse = 
    if self#requete_en_cours then
      raise Requete_en_cours;
    Tarotv.assimiler_requete_inviter joueur noms;    
    Tarotv.traiter_reponse joueur 
			   (function 
			     | Tarotv.Accepte -> reponse Accepte
			     | Tarotv.Refuse -> reponse Refuse
			     | Tarotv.Erreur -> reponse Interrompu);
    self#envoyer (Protocole.Inviter (Array.of_list noms))
  method priser prise reponse =
    if self#requete_en_cours then
      raise Requete_en_cours;
    Tarotv.assimiler_requete_prise joueur prise;    
    Tarotv.traiter_reponse joueur 
			   (function 
			     | Tarotv.Accepte -> reponse Accepte
			     | Tarotv.Refuse -> reponse Refuse
			     | Tarotv.Erreur -> reponse Interrompu);
    self#envoyer (Protocole.Prise prise)
  method appeler carte reponse =
    if self#requete_en_cours then
      raise Requete_en_cours;
    Tarotv.assimiler_requete_appel joueur carte;    
    Tarotv.traiter_reponse joueur 
			   (function 
			     | Tarotv.Accepte -> reponse Accepte
			     | Tarotv.Refuse -> reponse Refuse
			     | Tarotv.Erreur -> reponse Interrompu);
    self#envoyer (Protocole.Appeler carte)
  method ecarter cartes reponse =
    if self#requete_en_cours then
      raise Requete_en_cours;
    Tarotv.assimiler_requete_ecart joueur (Array.to_list cartes);    
    Tarotv.traiter_reponse joueur 
			   (function 
			     | Tarotv.Accepte -> reponse Accepte
			     | Tarotv.Refuse -> reponse Refuse
			     | Tarotv.Erreur -> reponse Interrompu);
    self#envoyer (Protocole.Ecart cartes)
  method jouer carte reponse =
    if self#requete_en_cours then
      raise Requete_en_cours;
    Tarotv.assimiler_requete_carte joueur carte;    
    Tarotv.traiter_reponse joueur 
			   (function 
			     | Tarotv.Accepte -> reponse Accepte
			     | Tarotv.Refuse -> reponse Refuse
			     | Tarotv.Erreur -> reponse Interrompu);
    self#envoyer (Protocole.Requete carte)
end
